﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using CetWin.Phone.Entity;

namespace CetWin.Phone
{


    public interface IWordSearch
    {
        Func<string, bool> Search { get; set; }

        Func<Word, bool> SearchByWord { get; set; }

        Func<Word, bool> FilterByType { get; set; }

        string SearchName { get; set; }

        WordType SearchType { get; set; }

        IList FilterWord(string searchKey);
    }

    public class DefaultWordSearchEngine : IWordSearch
    {
        public DefaultWordSearchEngine(string searchName)
        {
            this.SearchName = searchName;
            Search = new Func<string, bool>(SearchWord);
            SearchByWord = new Func<Word, bool>(SearchWord);
        }
        public Func<string, bool> Search { get; set; }
        public Func<Word, bool> SearchByWord { get; set; }
        public Func<Word, bool> FilterByType { get; set; }

        public string SearchName { get; set; }
        public WordType SearchType { get; set; }

        protected virtual bool SearchWord(string word)
        {
            return true;
        }

        protected virtual bool SearchWord(Word word)
        {
            return true;
        }

        public virtual IList FilterWord(string searchKey)
        {
            throw new NotImplementedException();
        }

        public virtual bool SearchByType(Word word)
        {
            return true;
        }
    }

    public class BaseWordSearchEngine : DefaultWordSearchEngine
    {

        public BaseWordSearchEngine(string searchName)
            : base(searchName)
        {

        }

        public bool IsCaseSensitive { get; set; }

        protected override bool SearchWord(string word)
        {
            return CheckWordLength(word, SearchName) && SearchFilerWord(word, SearchName);
        }

        private bool FilerChinese(string word, string ht)
        {
            if (ht == null) return false;
            return !string.IsNullOrEmpty(ht) && ht.Contains(word);
        }

        protected override bool SearchWord(Word word)
        {
            if (!IsCaseSensitive)
            {
                SearchName = SearchName.ToLower();
            }
            return SearchWord(IsCaseSensitive ? word.Name : word.Name.ToLower());
        }

        public override bool SearchByType(Word word)
        {
            return word.Type.Contains(SearchType);
        }

        //word: about searchName: a:5 return true
        private bool CheckWordLength(string word, string searchName)
        {
            int count = 0;
            var countStr = searchName.Split(new char[] { ':' });
            if (countStr.Length > 1 && !string.IsNullOrEmpty(countStr[1]))
                count = int.Parse(countStr[1]);
            if (count > 0)
                return word.Length == count;
            return true;
        }

        private bool SearchFilerWord(string word, string searchName)
        {
            if (searchName.Contains(":"))
            {
                searchName = searchName.Substring(0, searchName.IndexOf(":"));
            }

            var length = searchName.Length;
            var array = searchName.Split(new char[] { '*' });

            //a*
            if (array.Length == 1)
                return word.StartsWith(searchName);
            //*b or a*b

            if (array.Length == 2)
            {
                if (string.IsNullOrEmpty(array[0]))
                    return word.EndsWith(array[1]);
                else
                    return word.StartsWith(array[0]) && word.EndsWith(array[1]);
            }


            //a*ion,*i*on
            if (array.Length >= 3)
            {
                var list = new List<bool>();
                var count = array.Length - 2;
                var index = searchName.IndexOf("*");
                if ((word.Length - 1) < index)
                    index = word.Length - 1;

                var wordStr = word.Substring(index);
                for (int i = 0; i < count; i++)
                {
                    list.Add(wordStr.Contains(array[++i]));
                }
                //match start,middle,end
                return CheckStartEnd(word, array[0], true) && !list.Contains(false) && CheckStartEnd(word, array[array.Length - 1], false);
            }

            return true;
        }

        //check start or end
        //"" true "a" match start
        private bool CheckStartEnd(string word, string searchName, bool IsStart)
        {
            if (string.IsNullOrEmpty(searchName)) return true;
            if (IsStart)
                return word.StartsWith(searchName);
            else
                return word.EndsWith(searchName);
        }
    }

    public class WordSearchEngineFactory
    {
        private static BaseWordSearchEngine wordSearchEngine;

        public static Func<string, bool> GetDefaultSearch(string searchName)
        {
            _initSearchEngine(searchName);
            return wordSearchEngine.Search;
        }

        public static bool FilerChinese(string word, string ht)
        {
            if (ht == null) return false;
            return !string.IsNullOrEmpty(ht) && ht.Contains(word);
        }

        public static Func<Word, bool> GetWordSearch(string searchName, bool isCaseSensitive)
        {
            _initSearchEngine(searchName);
            wordSearchEngine.IsCaseSensitive = isCaseSensitive;
            return wordSearchEngine.SearchByWord;
        }

        public static Func<Word, bool> GetTypeFilter(string searchName, WordType searchType)
        {
            _initSearchEngine(searchName);
            wordSearchEngine.SearchType = searchType;
            return wordSearchEngine.SearchByType;
        }

        private static void _initSearchEngine(string searchName)
        {
            if (wordSearchEngine == null)
            {
                wordSearchEngine = new BaseWordSearchEngine(searchName);
            }
            wordSearchEngine.SearchName = searchName;
        }

    }
}
